package com.jse.server;

import java.io.IOException;
import java.util.List;
import java.util.ListIterator;
import java.util.Objects;
import java.util.function.Consumer;

public abstract class Filter {

    protected Filter () {}
    public static class Chain {

        private ListIterator<Filter> iter;
        private HttpHandler handler;
        public Chain (List<Filter> filters, HttpHandler handler) {
            iter = filters.listIterator();
            this.handler = handler;
        }
        
        public void doFilter(HttpExchange exchange) throws IOException {
            if (!iter.hasNext()) {
                handler.handle (exchange);
            } else {
                Filter f = iter.next();
                f.doFilter (exchange, this);
            }
        }
    }

    public abstract void doFilter(HttpExchange exchange, Chain chain)
        throws IOException;
    
    public abstract String getFilterName();

    public static Filter beforeHandler(String filterName,
                                       Consumer<HttpExchange> operation) {
        Objects.requireNonNull(filterName);
        Objects.requireNonNull(operation);
        return new Filter() {
            @Override
            public void doFilter(HttpExchange exchange, Chain chain) throws IOException {
                operation.accept(exchange);
                chain.doFilter(exchange);
            }
            @Override
            public String getFilterName() {
                return filterName;
            }
        };
    }

    public static Filter afterHandler(String filterName,
                                      Consumer<HttpExchange> operation) {
        Objects.requireNonNull(filterName);
        Objects.requireNonNull(operation);
        return new Filter() {
            @Override
            public void doFilter(HttpExchange exchange, Chain chain) throws IOException {
                chain.doFilter(exchange);
                operation.accept(exchange);
            }
            @Override
            public String getFilterName() {
                return filterName;
            }
        };
    }
    
}
